package in.muton.edushare.newentities.upgraded.multipleInvite;

import in.muton.edushare.EduShareSession;
import in.muton.edushare.components.autocomplete.api.Pair;
import in.muton.edushare.wicket.models.CayenneList;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.wicket.model.IModel;

import com.edushare.common.dao.PollsDAO;
import com.edushare.common.dao.UserPollDAO;
import com.edushare.common.orm.ORMInterface;
import com.edushare.common.vo.Batches;
import com.edushare.common.vo.CourseInstances;
import com.edushare.common.vo.Departments;
import com.edushare.common.vo.Enrolments;
import com.edushare.common.vo.GroupMembers;
import com.edushare.common.vo.Groups;
import com.edushare.common.vo.Poll;
import com.edushare.common.vo.Universities;
import com.edushare.common.vo.UserDeptLink;
import com.edushare.common.vo.UserPoll;
import com.edushare.common.vo.UserRoles;
import com.edushare.common.vo.Users;

public class PollMultipleInvite implements MultipleAudienceInvite {
	private static final long serialVersionUID = -855687249055484809L;
	public static final Log log = LogFactory.getLog(PollMultipleInvite.class);

	private IModel<Poll> poll;

	public PollMultipleInvite(IModel<Poll> poll) {
		this.poll = poll;
	}

	public List<String> inviteUsers(int role, boolean extraOptions,
			List<Pair<IModel<?>, CayenneList<Users>>> entityList) {
		log.debug("Number of entities = " + entityList.size());
		if (role != UserPoll.ROLE_REVIEWER) {
			if (extraOptions || entityList.size() == 1) {
				log.debug("Creating multiple polls");
				return createGroupAndAdd(role, entityList);
			} else {
				log.debug("Creating individual polls");
				return processSingleList(role, entityList);
			}
		} else {
			List<Poll> pollList = new ArrayList<Poll>();
			if (poll.getObject().getParentPoll() == null) {
				pollList.add(poll.getObject());
				pollList.addAll(poll.getObject().getChildrenPolls());
			} else {
				pollList.add(poll.getObject().getParentPoll());
				pollList.addAll(poll.getObject().getParentPoll()
						.getChildrenPolls());
			}
			List<String> status = new ArrayList<String>();
			for (Poll p : pollList) {
				status.addAll(inviteToPoll(p, role, entityList));
			}
			EduShareSession.get().getSessionORMInterface().commitAllChanges();
			return status;
		}
	}

	public List<String> getExtraOptions() {
		return extraOptions;
	}

	private void initializeSinglePoll() {
		poll.getObject().setPollGroupId(0);
		poll.getObject().setPollGroupType(Poll.POLL_INDI);
		poll.getObject().setPollSubgroup(Poll.POLL_MULTIPLE_AUDI);
	}

	private List<String> inviteToPoll(Poll poll, int role,
			List<Pair<IModel<?>, CayenneList<Users>>> audList) {
		List<String> status = new ArrayList<String>();
		ORMInterface orm = EduShareSession.get().getSessionORMInterface();
		UserPollDAO upDAO = new UserPollDAO(orm);
		for (Pair<IModel<?>, CayenneList<Users>> aud : audList) {
			List<Users> userList = aud.getV2().getUtilList();
			int count = 0;
			for (Users u : userList) {
				if (!upDAO.addUserToPoll(u, poll, role)) {
					status.add("User " + u.getCompleteUserName()
							+ " already present in poll " + poll.getPollName()
							+ " : " + poll.getPollAudi(orm));
				} else {
					count++;
				}
			}
			status.add("Added " + count + " users as observers to "
					+ poll.getPollName() + " : " + poll.getPollAudi(orm));
		}
		return status;
	}

	private List<String> processSingleList(int role,
			List<Pair<IModel<?>, CayenneList<Users>>> audList) {
		Integer i = poll.getObject().getPollGroupType();
		if (i == null || i == Poll.POLL_INDI)
			initializeSinglePoll();
		inviteToPoll(poll.getObject(), role, audList);
		List<String> status = new ArrayList<String>();
		poll.getObject().setStatus(Poll.POLL_STATUS_POLLING);
		status.add("Created new poll "
				+ poll.getObject().getPollName()
				+ " : "
				+ poll.getObject().getPollAudi(
						EduShareSession.get().getSessionORMInterface()));
		EduShareSession.get().getSessionORMInterface().commitAllChanges();
		return status;
	}

	private List<String> createGroupAndAdd(int role,
			List<Pair<IModel<?>, CayenneList<Users>>> entityList) {
		ORMInterface orm = EduShareSession.get().getSessionORMInterface();
		Poll parentPoll;
		List<String> status = new ArrayList<String>();
		log.debug("Inside creatingGroupAndAdd");
		log.debug("Size of the array is " + entityList.size());
		if (poll.getObject().getParentPoll() == null) {
			parentPoll = poll.getObject();
		} else {
			parentPoll = poll.getObject().getParentPoll();
		}
		PollsDAO pDAO = new PollsDAO(orm);
		for (Pair<IModel<?>, CayenneList<Users>> aud : entityList) {
			Poll newPoll;
			if (poll.getObject().getPollGroupType() == null)
				newPoll = poll.getObject();
			else {
				newPoll = pDAO.createNewPoll(parentPoll);
				pDAO.copyPollQuestions(newPoll, parentPoll);
			}
			UserPollDAO upDAO = new UserPollDAO(orm);
			List<Users> reviewersList = upDAO.getPollObservers(parentPoll);
			upDAO.addUsersToPoll(aud.getV2().getUtilList(), newPoll, role);
			upDAO
					.addUsersToPoll(reviewersList, newPoll,
							UserPoll.ROLE_REVIEWER);
			newPoll.setPollGroupId(getGroupId(aud.getV1()));
			newPoll.setPollGroupType(getGroupType(aud.getV1()));
			newPoll
					.setPollSubgroup(convertToAudience(aud.getV3(), aud.getV1()));
			newPoll.setStatus(Poll.POLL_STATUS_POLLING);
			log.debug("Added poll " + newPoll.getPollName() + " : "
					+ newPoll.getPollAudi(orm));
			status.add("Created new poll " + newPoll.getPollName() + " : "
					+ newPoll.getPollAudi(orm));
		}
		EduShareSession.get().getSessionORMInterface().commitAllChanges();
		return status;
	}

	public int getGroupType(IModel<?> model) {
		if (model == null)
			return Poll.POLL_INDI;
		if (model.getObject() instanceof Universities)
			return Poll.POLL_UNIV;
		if (model.getObject() instanceof Departments)
			return Poll.POLL_DEPT;
		if (model.getObject() instanceof CourseInstances)
			return Poll.POLL_COURSE;
		if (model.getObject() instanceof Batches)
			return Poll.POLL_BATCH;
		if (model.getObject() instanceof Groups)
			return Poll.POLL_GROUP;
		return Poll.POLL_INDI;
	}

	public int getGroupId(IModel<?> model) {
		if (model == null) {
			return 0;
		}
		if (model.getObject() instanceof Universities)
			return ((Universities) model.getObject()).getUniversityId();
		if (model.getObject() instanceof Departments)
			return ((Departments) model.getObject()).getDepartmentId();
		if (model.getObject() instanceof CourseInstances)
			return ((CourseInstances) model.getObject()).getCourseInstanceId();
		if (model.getObject() instanceof Groups)
			return ((Groups) model.getObject()).getGroupId();
		if (model.getObject() instanceof Batches)
			return ((Batches) model.getObject()).getBatchId();
		return 0;
	}

	public int convertToAudience(int role, IModel<?> model) {
		if (model == null)
			return Poll.POLL_MULTIPLE_AUDI;
		if (model.getObject() instanceof Universities) {
			switch (role) {
			case UserRoles.ADMIN_ROLE:
				return Poll.POLL_ADMINS;
			case UserRoles.TEACHER_ROLE:
				return Poll.POLL_FACULTY;
			case UserRoles.STUDENT_ROLE:
				return Poll.POLL_STUDENTS;
			}
		} else if (model.getObject() instanceof CourseInstances) {
			switch (role) {
			case Enrolments.TEACHER:
				return Poll.POLL_FACULTY;
			case Enrolments.TEACHING_ASSISTANT:
				return Poll.POLL_TA;
			case Enrolments.STUDENT:
				return Poll.POLL_STUDENTS;
			case Enrolments.OBSERVER:
				return Poll.POLL_STUDENTS;
			}
		} else if (model.getObject() instanceof Departments) {
			switch (role) {
			case UserDeptLink.PRIMARY_ADMIN:
				return Poll.POLL_ADMINS;
			case UserDeptLink.SECONDARY_ADMIN:
				return Poll.POLL_ADMINS;
			case UserDeptLink.STUDENT:
				return Poll.POLL_STUDENTS;
			case UserDeptLink.TEACHER:
				return Poll.POLL_FACULTY;
			}
		} else if (model.getObject() instanceof Groups) {
			switch (role) {
			case GroupMembers.GROUP_ADMIN:
				return Poll.POLL_ADMINS;
			case GroupMembers.GROUP_MEMBER:
				return Poll.POLL_MEMBERS;
			}
		}
		return 0;
	}

	private static List<String> extraOptions = new ArrayList<String>();
	static {
		extraOptions.add("Create a new poll for each group.");
	}
}
